/***
 * @Author: LVGRAPE
 * @Date: 2023-09-22 11:04:09
 * @LastEditTime: 2023-09-22 11:21:04
 * @LastEditors: LVGRAPE
 * @Description:
 * @FilePath: \ZINO_FC_V4\ZINO\hardware\si24r1\si24r1.h
 * @要啥没啥，爱咋咋的
 */

#ifndef __SI24R1_H_
#define __SI24R1_H_
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus

#include <stdint.h>
#include "si24r1_port.h"

#define SI24R1CMD_R_REG          0x00  // 读寄存器
#define SI24R1CMD_W_REG          0x20  // 写寄存器

    enum si24r1_reg_map {
        SI24R1_REG_CONFIG = 0,//配置寄存器
        SI24R1_REG_ENAA,//使能自动确认
        SI24R1_REG_EN_RXADDR,//使能接收数据管道地址
        SI24R1_REG_SETUP_AW,//地址宽度配置
        SI24R1_REG_SETUP_RETR,//自动重发配置
        SI24R1_REG_RF_CH,//射频信道
        SI24R1_REG_RF_SETUP,//射频配置
        SI24R1_REG_STATUS,//状态寄存器（SPI操作开始，状态寄存器值通过MISO串行输出)。
        SI24R1_REG_OBSERVE_TX,//发射结果统计
        SI24R1_REG_RSSI,//接收信号强度检测
        SI24R1_REG_RX_ADDR_P0,//数据管道0的接收地址，最大宽度为5bytes(LSByte最先写入，通过SETUP_AW配置地址宽度) 。
        SI24R1_REG_RX_ADDR_P1,//数据管道1的接收地址，最大宽度为5bytes(LSByte最先写入，通过SETUP_AW配置地址宽度) 。
        SI24R1_REG_RX_ADDR_P2,//数据管道2的接收地址，最大宽度为5bytes(LSByte最先写入，通过SETUP_AW配置地址宽度) 。
        SI24R1_REG_RX_ADDR_P3,//数据管道3的接收地址，最大宽度为5bytes(LSByte最先写入，通过SETUP_AW配置地址宽度) 。
        SI24R1_REG_RX_ADDR_P4,//数据管道4的接收地址，最大宽度为5bytes(LSByte最先写入，通过SETUP_AW配置地址宽度) 。
        SI24R1_REG_RX_ADDR_P5,//数据管道5的接收地址，最大宽度为5bytes(LSByte最先写入，通过SETUP_AW配置地址宽度) 。
        SI24R1_REG_TX_ADDR,//发射方的发射地址(LSByte最先写入)，如果发射放需要收ACK确认信号，则需要配置RX_ADDR_P0的值等于TX_ADDR，并使能ARQ。
        SI24R1_REG_RX_PW_P0,//接收数据管道0数据字节数
        SI24R1_REG_RX_PW_P1,//接收数据管道1数据字节数
        SI24R1_REG_RX_PW_P2,//接收数据管道2数据字节数
        SI24R1_REG_RX_PW_P3,//接收数据管道3数据字节数
        SI24R1_REG_RX_PW_P4,//接收数据管道4数据字节数
        SI24R1_REG_RX_PW_P5,//接收数据管道5数据字节数
        SI24R1_REG_FIFO_STATUS,//FIFO状态
        SI24R1_REG_DYNPD = 0x1C,//使能动态负载长度
        SI24R1_REG_FEATURE,//特征寄存器
    };
    enum si24r1_commands{
        SI24R1_CMD_R_REGISTER = 0X1F,//000A AAAA,1 to 5 LSByte first,读寄存器命令， AAAAA表示寄存器地址（参考寄存器表）。
        SI24R1_CMD_W_REGISTER = 0X20,//001A AAAA,1 to 5 LSByte first,读寄存器命令， AAAAA表示寄存器地址（参考寄存器表）。只允许Shutdown、 Standby、 Idle-TX模式下操作。
        SI24R1_CMD_R_RX_PAYLOAD = 0X61,//0110 0001 从FIFO中读收到的数据， 1-32字节，读出后FIFO数据被删除。适用于接收模式。
        SI24R1_CMD_W_TX_PAYLOAD = 0XA0,//1010 0000 写发射负载数据，大小为1-32字节，适用于发射模式。
        SI24R1_CMD_FLUSH_TX = 0XE1,//1110 0001 清空TX FIFO，适用于发射模式。
        SI24R1_CMD_FLUSH_RX = 0XE2,//1110 0010 清空RX FIFO，适用于接收模式。如果需要回ACK，则不能在回ACK操作完成前进行清空FIFO，否则视为通信失败。
        SI24R1_CMD_REUSE_TX_PL = 0XE3,//1110 0011 适用于发送方，清空TX FIFO或对FIFO写入新的数据后不能使用该命令。
        SI24R1_CMD_R_RX_PL_WID = 0X60,//0110 0000 读取收到的数据字节数。
        SI24R1_CMD_W_ACK_PAYLOAD = 0XA8,//1010 1PPP 适用于接收方，通过PIPE PPP将数据通过ACK的形式发出去，最多允许三帧数据存于FIFO中。
        SI24R1_CMD_W_TX_PAYLOAD_NOACK = 0XB0,//1011 0000 适用于发射模式，使用这个命令同时需要将AUTOACK位置1。
        SI24R1_CMD_NOP = 0XFF,//1111 1111 无操作。可用于返回STATUS值。
    };
    typedef struct si24r1_reg_value {
        struct {//配置寄存器
            /**发射/接收配置，只能在Shutdown和Standby下更改
             * 1：接收模式
             * 0：发射模式 */
            uint8_t PRIM_RX : 1;
            /**关断/开机模式配置
             * 0：关断模式
             * 1：开机模式 */
            uint8_t PWR_UP : 1;
            /**CRC长度配置，
             * 0： 1byte
             * 1： 2 bytes */
            uint8_t CRCO : 1;
            /**使能CRC。如果EN_AA不全为零时， EN_CRC必须为1。
             * 0：关闭CRC
             * 1：开启CRC */
            uint8_t EN_CRC : 1;
            /**最大重发计数中断屏蔽控制
             * 0：最大重发计数中断使能， MAX_RT中断标志在
             * IRQ引脚上产生中断信号，低电平有效
             * 1：最大重发计数中断关闭， MAX_RT中断标志不影响IRQ引脚输出 */
            uint8_t MASK_MAX_RT : 1;
            /**发射中断屏蔽控制
             * 0：发射中断使能， TX_DS中断标志在IRQ引脚上
             * 产生中断信号，低电平有效
             * 1：发射中断关闭， TX_DS中断标志不影响IRQ引脚输出 */
            uint8_t MASK_TX_DS : 1;
            /**接收中断屏蔽控制
             * 0：接收中断使能， RX_DR中断标志在IRQ引脚上
             * 产生中断信号，低电平有效
             * 1：接收中断关闭， RX_DR中断标志不影响IRQ引脚输出 */
            uint8_t MASK_RX_DR : 1;
            uint8_t res : 1;
        }config;
        struct {//使能自动确认
            uint8_t ENAA_P0 : 1;//使能数据管道0自动确认
            uint8_t ENAA_P1 : 1;//使能数据管道1自动确认
            uint8_t ENAA_P2 : 1;//使能数据管道2自动确认
            uint8_t ENAA_P3 : 1;//使能数据管道3自动确认
            uint8_t ENAA_P4 : 1;//使能数据管道4自动确认
            uint8_t ENAA_P5 : 1;//使能数据管道5自动确认
            uint8_t res : 2;
        }en_aa;
        struct {//使能接收数据管道地址
            uint8_t ERX_P0 : 1;//使能数据管道0
            uint8_t ERX_P1 : 1;//使能数据管道1
            uint8_t ERX_P2 : 1;//使能数据管道2
            uint8_t ERX_P3 : 1;//使能数据管道3
            uint8_t ERX_P4 : 1;//使能数据管道4
            uint8_t ERX_P5 : 1;//使能数据管道5
            uint8_t res : 2;
        }en_rxaddr;
        struct {//地址宽度配置
            /**发射方/接收方地址宽度
             * 00：错误值
             * 01： 3bytes
             * 10： 4bytes
             * 11： 5bytes */
            uint8_t AW : 2;
            uint8_t res : 6;
        }setup_aw;
        struct {//自动重发配置
            /**最大自动重发次数
             * 0000：关闭自动重发
             * 0001： 1次
             * 0010： 2次
             * ……
             * 1111： 15次 */
            uint8_t ARC : 4;
            /**自动重发延时配置
             * 0000： 250uS
             * 0001： 500uS
             * 0010： 750uS
             * ……
             * 1111： 4000uS */
            uint8_t ARD : 4;
        }setup_retr;
        struct {//射频信道
            /**设置芯片工作时的信道，分别对应1~125个道
             * 信道间隔为1MHZ,默认为02即2402MHz */
            uint8_t RF_CH : 7;
            uint8_t res : 1;
        }rf_ch;
        struct {//射频配置
            /**设置TX发射功率
             * 111: 7dBm 110: 4dBm
             * 101: 3dBm 100: 1dBm
             * 011: 0dBm 010:-4dBm
             * 001:-6dBm 000:-12dBm */
            uint8_t RF_PWR : 3;
            /**设置射频数据率
             * [RF_DR_LOW, RF_DR_HIGH]:
             * 00： 1Mbps
             * 01： 2Mbps
             * 10： 250kbps
             * 11：保留 */
            uint8_t RF_DR_HIGH : 1;
            uint8_t PLL_LOCK : 1;//保留字，必须为0
            /**设置射频数据率为250kbps 、 1Mbps或2Mbps，
             * 与RF_DR_HIGH共同控制 */
            uint8_t RF_DR_LOW : 1;
            uint8_t res : 1;
            uint8_t CONT_WAVE : 1;//为’1’时，使能恒载波发射模式
        }rf_setup;
        struct {//状态寄存器
            uint8_t TX_FULL : 1;//TX FIFO满标志位。
            uint8_t RX_P_NO : 3;//收到数据的接收管道PPP号，可以通过SPI读出。000-101：数据管道0-5 110：不可用 111： RX FIFO为空
            uint8_t MAX_RT : 1;//达到最大重发次数中断位，写’1’清除。
            uint8_t TX_DS : 1;//发射端发射完成中断位，如果是ACK模式，则收到ACK确认信号后TX_DS位置1，写’1’清除。
            uint8_t RX_DR : 1;//RX FIFO有值标志位，写’1’清除。
            uint8_t res : 1;
        }status;
        struct {//发射结果统计
            /**重发计数。发射一个新包时， ARC_CNT从0开始计数。 */
            uint8_t ARC_CNT : 4;
            /**丢包计数。最大计数为15，改变RF_CH后PLOS_CNT从0开始计数。 */
            uint8_t PLOS_CNT : 4;
        }observe_tx;
        struct {//接收信号强度检测
            uint8_t RSSI : 1;//接收信号强度： 0：接收信号小于<-60dBm
            uint8_t res : 7;
        }rssi;
        struct {
            uint8_t addr[5];
        }rx_addr_p0;
        struct {
            uint8_t addr[5];
        }rx_addr_p1;
        struct {
            uint8_t addr;
        }rx_addr_p2;
        struct {
            uint8_t addr;
        }rx_addr_p3;
        struct {
            uint8_t addr;
        }rx_addr_p4;
        struct {
            uint8_t addr;
        }rx_addr_p5;
        struct {//发射方的发射地址(LSByte最先写入)，如果发射放需要收ACK确认信号，则需要配置RX_ADDR_P0的值等于TX_ADDR，并使能ARQ。
            uint8_t addr[5];
        }tx_addr;
        struct {
            uint8_t RX_PW_P0 : 6;//接收数据管道0数据字节数(1—32Bytes)。1： 1byte …… 32： 32bytes
            uint8_t res : 2;
        }rx_pw_p0;
        struct {
            uint8_t RX_PW_P1 : 6;//接收数据管道1数据字节数(1—32Bytes)。1： 1byte …… 32： 32bytes
            uint8_t res : 2;
        }rx_pw_p1;
        struct {
            uint8_t RX_PW_P2 : 6;//接收数据管道2数据字节数(1—32Bytes)。1： 1byte …… 32： 32bytes
            uint8_t res : 2;
        }rx_pw_p2;
        struct {
            uint8_t res : 2;
            uint8_t RX_PW_P3 : 6;//接收数据管道3数据字节数(1—32Bytes)。1： 1byte …… 32： 32bytes
        }rx_pw_p3;
        struct {
            uint8_t RX_PW_P4 : 6;//接收数据管道4数据字节数(1—32Bytes)。1： 1byte …… 32： 32bytes
            uint8_t res : 2;
        }rx_pw_p4;
        struct {
            uint8_t RX_PW_P5 : 6;//接收数据管道5数据字节数(1—32Bytes)。1： 1byte …… 32： 32bytes
            uint8_t res : 2;
        }rx_pw_p5;
        struct {//FIFO状态
            uint8_t RX_EMPTY : 1;//RX FIFO空标志 1： RX FIFO为空 0： RX FIFO有数据
            uint8_t RX_FULL : 1;//RX FIFO满标志 1： RX FIFO满 0： RX FIFO可写
            uint8_t res : 2;
            uint8_t TX_EMPTY : 1;//TX FIFO空标志 1： TX FIFO为空 0： TX FIFO有数据
            uint8_t TX_FULL : 1;//TX FIFO满标志 1： TX FIFO满 0： TX FIFO可写
            uint8_t TX_REUSE : 1;//只用于发射端， FIFO数据重新利用 当用RESUSE_TX_PL命令后，发射上次已成功发射的数据，通过W_TX_PAYLOAD或FLUSH TX命令关闭该功能
            uint8_t res2 : 1;
        }fifo_status;
        struct {//使能动态负载长度
            uint8_t DPL_P0 : 1;//使能接收管道0动态负载长度(需EN_DPL及ENAA_P0)。
            uint8_t DPL_P1 : 1;//使能接收管道1动态负载长度(需EN_DPL及ENAA_P1)。
            uint8_t DPL_P2 : 1;//使能接收管道2动态负载长度(需EN_DPL及ENAA_P2)。
            uint8_t DPL_P3 : 1;//使能接收管道3动态负载长度(需EN_DPL及ENAA_P3)。
            uint8_t DPL_P4 : 1;//使能接收管道4动态负载长度(需EN_DPL及ENAA_P4)。
            uint8_t DPL_P5 : 1;//使能接收管道5动态负载长度(需EN_DPL及ENAA_P5)。
            uint8_t res : 2;
        }dynpd;
        struct {
            uint8_t EN_DYN_ACK : 1;//使能命令W_TX_PAYLOAD_NOACK
            uint8_t EN_ACK_PAYd : 1;//使能ACK负载(带负载数据的ACK包)
            uint8_t EN_DPL : 1;//使能动态负载长度
            uint8_t res : 5;
        }feature;
    }__attribute__((packed)) si24r1_regs_t;
    enum SI24R1_ROLE {
        SI24R1_ROLE_TX = 0,
        SI24R1_ROLE_RX = 1,
    };
    enum SI24R1_TX_POWER {
        SI24R1_TX_POWER_N12dBm = 0,
        SI24R1_TX_POWER_N6dBm,
        SI24R1_TX_POWER_N4dBm,
        SI24R1_TX_POWER_0dBm,
        SI24R1_TX_POWER_1dBm,
        SI24R1_TX_POWER_3dBm,
        SI24R1_TX_POWER_4dBm,
        SI24R1_TX_POWER_7dBm,
    };
    enum SI24R1_BANDWITH {
        SI24R1_BANDWITH_1M = 0,
        SI24R1_BANDWITH_2M,
        SI24R1_BANDWITH_250K,
    };
    typedef struct si24r1_user_config {
        enum SI24R1_ROLE role;
        enum SI24R1_TX_POWER tx_power;
        enum SI24R1_BANDWITH band;
        uint8_t channel;
        uint8_t address[5];
    }__attribute__((packed)) si24r1_user_t;
    
    struct si24r1 {
        struct hal_si24r1_port port;
        si24r1_regs_t onchip_config;//所有寄存器值
        si24r1_user_t user_config;//用来配置RC对频及通信时参数
        struct si24r1_flag{
            uint8_t activated_features : 1;
            uint8_t using_irq : 1;
        } flags;
        struct si24r1_callback *cb;

        uint8_t status;

        rt_sem_t sem;   // irq
        rt_sem_t send_sem;

    };
    struct si24r1_callback
    {
        void (*rx_ind)(struct si24r1 *s, uint8_t* data, uint8_t len, int pipe);
        void (*tx_done)(struct si24r1 *s, int pipe);
    };
    rt_err_t si24r1_init(struct si24r1 *s, char *spi_name, int ce_pin, int iqr_pin, struct si24r1_callback *cb);
    void si24r1_update_user_config(struct si24r1* s);
    void si24r1_update_onchip_config(struct si24r1* s);
    void si24r1_fill_default_config(struct si24r1* s);
    int si24r1_send_data(struct si24r1 *s, uint8_t* data, uint8_t len, uint8_t pipe);
    int si24r1_run(struct si24r1* s);
    void si24r1_check_all_reg(struct si24r1* s);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif
